package com.whately.core.base.verifycode.slider;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.RandomUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 滑块验证工具类
 */
public class SliderImageUtil {
    //private final int ORI_WIDTH = 240;  //源文件宽度
    //private final int ORI_HEIGHT = 146;  //源文件高度


    private static int targetWidth =55;//小图长
    private static int targetHeight=46;//小图高
    private static int circleR=6;//半径
    private static int r1=3;//距离点

    public static void main(String[] args) throws Exception {

        SliderModel model = new SliderModel();
        InputStream stream = new FileInputStream("/Users/qinchao/Desktop/tmp/test/static/targets/13.jpg");
        BufferedImage bufferedImage = ImageIO.read( stream);

        int ORI_WIDTH = bufferedImage.getWidth();
        int ORI_HEIGHT = bufferedImage.getHeight();

        //生成切图的坐标
        geneCord(ORI_WIDTH,ORI_HEIGHT,model);

        //切图
        BufferedImage cutImage= new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);
        int[][] rect= getBlockData();
        cutByTemplate(bufferedImage,cutImage,rect,model.getX(),model.getY());

       // System.out.println("data:image/jpg;base64,"+getImageBASE64(cutImage));

    }

    public  SliderModel pictureTemplatesCut() throws Exception {
        SliderModel model = new SliderModel();
        int target = RandomUtils.nextInt(1,13);
        InputStream stream = getClass().getClassLoader().getResourceAsStream("static/slider/targets/"+target+".jpg");
        BufferedImage bufferedImage = ImageIO.read( stream);

        int ORI_WIDTH = bufferedImage.getWidth();
        int ORI_HEIGHT = bufferedImage.getHeight();

        //生成切图的坐标
        geneCord(ORI_WIDTH,ORI_HEIGHT,model);

        //切图
        BufferedImage cutImage= new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);
        int[][] rect= getBlockData();
        cutByTemplate(bufferedImage,cutImage,rect,model.getX(),model.getY());


        model.setBackgroundImages(getImageBytes(bufferedImage));
        model.setMaskImages(getImageBytes(cutImage));

        return model;
    }

    private static void geneCord(int ORI_WIDTH,int ORI_HEIGHT,SliderModel model){
        //随机生成坐标
        //x [ 10, ORI_WIDTH - targetWidth -5] = [10,180] , [10,180]
        int xMin = targetWidth+10;
        int xMax =  ORI_WIDTH - targetWidth -5;

        int x = RandomUtils.nextInt(xMin,xMax+1);

        // y [10,ORI_HEIGHT - targetHeight - 10 ] = [10,90]
        int yMin = targetHeight+10;
        int yMax = ORI_HEIGHT - targetHeight - 10;

        int y = RandomUtils.nextInt(yMin,yMax+1);

        //TODO 去掉
        //x = 150;
        //y = 73;

        model.setXPrecent(x*100/ORI_WIDTH);
        model.setYPrecent(y*100/ORI_HEIGHT);

        model.setX(x);
        model.setY(y);
    }


    //**将rgb色彩值转成16进制代码**
    private static String toHexFromColor(Color color){
        String r,g,b;
        StringBuilder su = new StringBuilder();
        r = Integer.toHexString(color.getRed());
        g = Integer.toHexString(color.getGreen());
        b = Integer.toHexString(color.getBlue());
        r = r.length() == 1 ? "0" + r : r;
        g = g.length() ==1 ? "0" +g : g;
        b = b.length() == 1 ? "0" + b : b;
        r = r.toUpperCase();
        g = g.toUpperCase();
        b = b.toUpperCase();
        su.append("0xFF");
        su.append(r);
        su.append(g);
        su.append(b);
        //0xFF0000FF
        return su.toString();
    }


    private static void cutByTemplate(BufferedImage oriImage,BufferedImage targetImage, int[][] templateImage, int x,int y){
        for (int i = 0; i < targetWidth; i++) {
            for (int j = 0; j < targetHeight; j++) {
                int rgb = templateImage[i][j];
                // 原图中对应位置变色处理
                int rgb_ori = oriImage.getRGB(x + i, y + j);

                if (rgb == 1) {
                    //抠图上复制对应颜色值
                    targetImage.setRGB(i, j, rgb_ori);
                    //原图对应位置颜色变化
                    //rgb_ori & 0x363636
                    oriImage.setRGB(x + i, y + j, 0xffffffff);
                }else if(rgb > 20 ){
                    targetImage.setRGB(i, j, 0xFFFFFF00);
                }else{
                    //这里把背景设为透明
                    targetImage.setRGB(i, j, rgb_ori & 0x00ffffff);
                }
            }
        }
    }

    private static int[][] getBlockData() {

        int[][] data = new int[targetWidth][targetHeight];
        double x2 = targetWidth -circleR;

        //随机生成圆的位置
        //double h1 = 6+circleR + Math.random() * (targetHeight-3*circleR-r1);

        int h1 = RandomUtils.nextInt(6+circleR ,Math.min(targetHeight,targetWidth) - 2*circleR-r1);
        double po = circleR*circleR;

        //xbegin ，右侧线条开始的位置
        double xbegin = targetWidth -circleR-r1;

        //ybegin ，上侧线条开始的位置
        double ybegin = targetHeight-circleR-r1;

        //小图的边框
        int border = 3;

        for (int i = 0; i < targetWidth; i++) {
            for (int j = 0; j < targetHeight; j++) {

                if(i<border){
                    //左侧
                    data[i][j] = 21;
                }else if(j>=targetHeight-border && i<=xbegin ){
                    //下
                    data[i][j] = 21;
                }else if(j<border&&i<=xbegin&& (i<h1-circleR || i > h1+circleR)){
                    //上
                    data[i][j] = 21;
                }else if((i<=xbegin&&i>xbegin-border) && (j<h1-circleR || j > h1+circleR)){
                    //右侧
                    data[i][j] = 21;
                }else{

                    double d3 = Math.pow(i - x2,2) + Math.pow(j - h1,2);
                    double d2 = Math.pow(j-2,2) + Math.pow(i - h1,2);
                    if ((j <= ybegin && d2 <= po)||(i >= xbegin && d3 >= po)) {
                        data[i][j] = 0;
                    }  else {
                        data[i][j] = 1;
                    }

                }

            }
        }


        int tmp = (int) Math.floor(h1-circleR);

        //上测的圆弧
        for(int i=Math.min(tmp,0);i<=tmp+2*circleR;i++){
            if(i>=targetWidth){
                break;
            }
            int tmpBorder = 2;
            for (int j = 0; j < targetHeight; j++) {
                if(data[i][j] == 21){
                    break;
                }else if(data[i][j] ==1){
                    //System.out.println("i = "+i+",j = "+j);
                    data[i][j] = 25;
                    tmpBorder--;
                    if(tmpBorder<=0){
                        break;
                    }

                }
            }
        }

        //右侧圆弧-- 右边上半
        int tmpXBeginInt = (int) Math.floor(xbegin);
        for(int i=tmpXBeginInt;i<=tmpXBeginInt+circleR+2;i++){
            if(i>=targetWidth){
                break;
            }

            int tmpBorder = 1;
            for (int j = 0; j < targetHeight; j++) {

                if(data[i][j] ==21 || data[i][j] == 25){
                    break;
                }else if(data[i][j] ==1){
                    data[i][j] = 26;

                    tmpBorder--;
                    if(tmpBorder<=0){
                        break;
                    }
                }
            }
        }

        //右侧圆弧-- 右边下半
        for(int i=tmpXBeginInt;i<=tmpXBeginInt+circleR+2;i++){
            if(i>=targetWidth){
                break;
            }

            int tmpBorder = 1;
            for (int j = targetHeight-1; j >=0; j--) {

                if(data[i][j] ==21 || data[i][j] == 25 || data[i][j] == 26){
                    break;
                }else if(data[i][j] ==1){
                    data[i][j] = 27;

                    tmpBorder--;
                    if(tmpBorder<=0){
                        break;
                    }
                }
            }
        }

        return data;
    }


    public static byte[] getImageBytes(BufferedImage image) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(image,"png",out);
        byte[] b = out.toByteArray();//转成byte数组
        return b;
    }


    public static String getImageBASE64(BufferedImage image) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(image,"png",out);
        byte[] b = out.toByteArray();//转成byte数组
        return Base64.encodeBase64String(b);//生成base64编码
    }


}


